home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-02-20 | 17.1 KB | 566 lines | [TEXT/MMCC] |
- // *****************************************************************************
- //
- // WindoidUtil.c
- //
- // —————————————————————————————————————————————————————————————————————————————
- // Copyright © 1991-95 Infinity Systems. All rights reserved.
- // —————————————————————————————————————————————————————————————————————————————
- // DESCRIPTION:
- // This file contains utility routines that the Infinity Windoid
- // WDEF uses in order to get its job done.
- // —————————————————————————————————————————————————————————————————————————————
- // WRITTEN BY:
- // Troy Gaul (tgaul@halcyon.com)
- // Infinity Systems
- // *****************************************************************************
-
- #include "WindoidUtil.h"
-
- #include <GestaltEqu.h>
- #include <Memory.h>
-
- #include "WindoidDraw.h"
- #include "WindoidTypes.h"
-
-
- // *****************************************************************************
- //
- // Environment-determining Routines
- //
- // —————————————————————————————————————————————————————————————————————————————
- // These use SysEnvirons by default so we don’t have to rely on Gestalt
- // being available and so MPW won’t include that code in our resource.
- // This can be changed by defining qUseGestalt to be 1.
- // *****************************************************************************
-
- // —————————————————————————————————————————————————————————————————————————————
- //
- // HasSystem7
- //
- // —————————————————————————————————————————————————————————————————————————————
- Boolean
- HasSystem7()
- {
- #if qUseGestalt || SystemSevenOrLater
- long vers = 0;
-
- return (Gestalt(gestaltSystemVersion, &vers) == noErr
- && ((vers & 0xFFFF) >= 0x0700));
- #else
- SysEnvRec theWorld;
-
- return (SysEnvirons(1, &theWorld) == noErr
- && theWorld.systemVersion >= 0x0700);
- #endif
- }
-
-
- // —————————————————————————————————————————————————————————————————————————————
- //
- // HasCQDraw
- //
- // —————————————————————————————————————————————————————————————————————————————
- Boolean
- HasCQDraw()
- {
- #if qUseGestalt || SystemSevenOrLater
- long vers = 0;
-
- return (Gestalt(gestaltQuickdrawVersion, &vers) == noErr
- && (vers & 0xFF00));
- #else
- SysEnvRec theWorld;
-
- return ((SysEnvirons(1, &theWorld) == noErr) &&
- theWorld.hasColorQD);
- #endif
- }
-
-
- // —————————————————————————————————————————————————————————————————————————————
- //
- // SyncPorts
- //
- // —————————————————————————————————————————————————————————————————————————————
- // Straight from the pages of _Macintosh Programming Secrets_, Second
- // Edition by Scott Knaster and Keith Rollin (page 425). (except that this
- // version doesn’t check Gestalt, it will only be called if CQD is running)
- // This routines was added to 2.3. It makes sure the drawing environment
- // is set correctly if the system has color. This is not needed for the
- // code in this WDEF as it is, but if a DoWDrawGIcon handler is implemented,
- // this is needed to make sure the drawing environment is set as Apple
- // tells us it will be for drawing the gray, xor’ed border.
- // —————————————————————————————————————————————————————————————————————————————
- void
- SyncPorts()
- {
- GrafPtr bwPort;
- CGrafPtr colorPort;
-
- GetWMgrPort(&bwPort);
- GetCWMgrPort(&colorPort);
- SetPort((GrafPtr) colorPort);
-
- BlockMoveData(&bwPort->pnLoc, &colorPort->pnLoc, 10);
- BlockMoveData(&bwPort->pnVis, &colorPort->pnVis, 14);
- PenPat((ConstPatternParam) &bwPort->pnPat);
- BackPat((ConstPatternParam) &bwPort->bkPat);
- }
-
-
- // —————————————————————————————————————————————————————————————————————————————
- //
- // OurDeviceLoop
- //
- // —————————————————————————————————————————————————————————————————————————————
- // Under System 7, calls through to the System’s DeviceLoop, on Systems
- // earlier than that, simulates the same behavior (perhaps a little more
- // inefficiently, however, since I don’t group similar devices).
- // —————————————————————————————————————————————————————————————————————————————
- #if !SystemSevenOrLater
-
- void
- OurDeviceLoop(RgnHandle drawingRgn, DeviceLoopDrawingUPP drawingProc,
- long userData, DeviceLoopFlags flags)
- {
- if (HasSystem7())
- DeviceLoop(drawingRgn, drawingProc, userData, flags);
- // This works with or without Color Quickdraw.
-
- else
- CallDeviceLoopDrawingProc(drawingProc, 1, 0, nil, userData);
- // We used to emulate a DeviceLoop using Device Manager calls,
- // but since System 6 coloring of the WDEF was dropped, we can
- // skip all that and call just the drawing routine directly.
- }
-
-
- #endif
- // *****************************************************************************
- //
- // Color Mixing Routines
- //
- // *****************************************************************************
-
- // —————————————————————————————————————————————————————————————————————————————
- //
- // UseDefaultColor
- //
- // —————————————————————————————————————————————————————————————————————————————
- // This routine will return some defaults in case neither the window’s
- // color table nor the System’s is long enough to contain the color
- // requested. It was provided by Jim Petrick as part of a fix for a bug
- // in version 2.3 of the Infinity Windoid. This problem would be seen if
- // a custom WCTB was being used which was not as long as the default
- // System one (or if the System one had been changed to a shorter size).
- // The rest of Jim’s fix can be found in GetWctbColor.
- // —————————————————————————————————————————————————————————————————————————————
- static void
- UseDefaultColor(short index, RGBColor *theColor)
- {
- switch (index) {
- case wContentColor: // 0
- case wTitleBarColor: // 4
- case wHiliteColorLight: // 5
- case wTitleBarLight: // 7
- theColor->red = theColor->green = theColor->blue = 0xFFFF;
- break;
-
- case wDialogLight: // 9
- case wTingeLight: // 11
- theColor->red = theColor->green = 0xCCCC;
- theColor->blue = 0xFFFF;
- break;
-
- case wTingeDark: // 12
- theColor->red = theColor->green = 0x3333;
- theColor->blue = 0x6666;
- break;
-
- default:
- theColor->red = theColor->green = theColor->blue = 0;
- break;
- }
- }
-
-
- // —————————————————————————————————————————————————————————————————————————————
- //
- // GetWctbColor
- //
- // —————————————————————————————————————————————————————————————————————————————
- // Given a partCode, return the RGBColor associated with it. (Using the
- // default window color table.)
- // —————————————————————————————————————————————————————————————————————————————
- static void
- GetWctbColor(WindowPeek window, short partCode, RGBColor *theColor)
- {
- AuxWinHandle awHndl;
- short count;
-
- // Get the Color table for the window if it has one.
- (void) GetAuxWin((WindowPtr) window, &awHndl);
- count = (**(WCTabHandle) (**awHndl).awCTable).ctSize;
-
- // If the table didn’t contain the entry of interest, look to the
- // default table.
- if (count < partCode) {
- (void) GetAuxWin(nil, &awHndl);
- count = (**(WCTabHandle) (**awHndl).awCTable).ctSize;
- }
-
- // If the entry is there, use it, if not make a best guess at a default value.
- if (count < partCode)
- UseDefaultColor(partCode, theColor);
- else
- *theColor = (**(WCTabHandle) (**awHndl).awCTable).ctTable[partCode].rgb;
- }
-
-
- // —————————————————————————————————————————————————————————————————————————————
- //
- // WctbForeColor
- //
- // —————————————————————————————————————————————————————————————————————————————
- void
- WctbForeColor(WindowPeek window, short partCode)
- {
- RGBColor theColor;
-
- GetWctbColor(window, partCode, &theColor);
- RGBForeColor(&theColor);
- }
-
-
- // —————————————————————————————————————————————————————————————————————————————
- //
- // WctbBackColor
- //
- // —————————————————————————————————————————————————————————————————————————————
- void
- WctbBackColor(WindowPeek window, short partCode)
- {
- RGBColor theColor;
-
- GetWctbColor(window, partCode, &theColor);
- RGBBackColor(&theColor);
- }
-
-
- // —————————————————————————————————————————————————————————————————————————————
- //
- // MixColor
- //
- // —————————————————————————————————————————————————————————————————————————————
- // Note: MixColor uses pragma processor 68020 to reduce code size with
- // MPW. This is okay because MixColor will only be called if we are
- // doing System 7 color, which requires Color Quickdraw, which is only
- // available on systems with 68020’s or better. If it isn’t compiled this
- // way, several glue routines will be added to the code WDEF resource to
- // handle the long integer arithmetic.
- // —————————————————————————————————————————————————————————————————————————————
- #pragma processor 68020
-
- static void
- MixColor(const RGBColor *light, const RGBColor *dark, short shade,
- RGBColor *result)
- {
- shade = 0x0F - shade;
- // This is necessary because we give shades between light and
- // dark (0% is light), but for colors, $0000 is black and $FFFF
- // is dark.
-
- result->red = (long) (light->red - dark->red) * shade / 15 + dark->red;
- result->green = (long) (light->green - dark->green) * shade / 15 + dark->green;
- result->blue = (long) (light->blue - dark->blue) * shade / 15 + dark->blue;
- }
-
-
- #pragma processor 68000
- // —————————————————————————————————————————————————————————————————————————————
- //
- // AvgWctbColor
- //
- // —————————————————————————————————————————————————————————————————————————————
- // Mix two parts by the given shade, which is actually a value
- // between 0 (0%) and 15 (100%), return the RGBColor.
- // —————————————————————————————————————————————————————————————————————————————
- static void
- AvgWctbColor(WindowPeek window, short light, short dark, short shade,
- RGBColor *theColor)
- {
- RGBColor lightColor;
- RGBColor darkColor;
-
- GetWctbColor(window, light, &lightColor);
- GetWctbColor(window, dark, &darkColor);
- MixColor(&lightColor, &darkColor, shade, theColor);
- }
-
-
- // —————————————————————————————————————————————————————————————————————————————
- //
- // AvgWctbForeColor
- //
- // —————————————————————————————————————————————————————————————————————————————
- void
- AvgWctbForeColor(WindowPeek window, short light, short dark, short shade)
- {
- RGBColor theColor;
-
- AvgWctbColor(window, light, dark, shade, &theColor);
- RGBForeColor(&theColor);
- }
-
-
- // —————————————————————————————————————————————————————————————————————————————
- //
- // AvgWctbBackColor
- //
- // —————————————————————————————————————————————————————————————————————————————
- void
- AvgWctbBackColor(WindowPeek window, short light, short dark, short shade)
- {
- RGBColor theColor;
-
- AvgWctbColor(window, light, dark, shade, &theColor);
- RGBBackColor(&theColor);
- }
-
-
- // *****************************************************************************
- //
- // CheckDisplay -- Check to see if we are using color title bars
- //
- // *****************************************************************************
-
- // —————————————————————————————————————————————————————————————————————————————
- //
- // CheckAvailable
- //
- // —————————————————————————————————————————————————————————————————————————————
- // Given a light and dark index value, a count, and and an array of
- // ‘percentage’ values (0x0 to 0xF, or 0 to 15), see if each of the
- // values in the ramp maps to a different color on the screen. If not,
- // we need to use black-and-white.
- // —————————————————————————————————————————————————————————————————————————————
- static Boolean
- CheckAvailable(WindowPeek window, short light, short dark, short count,
- short *ramp)
- {
- RGBColor theColor;
- short i;
- short colorIndex = 0;
- short lastIndex;
-
- for (i = 0 ; i < count ; i++) {
- AvgWctbColor(window, light, dark, ramp[i], &theColor);
-
- lastIndex = colorIndex;
- colorIndex = Color2Index(&theColor);
-
- if (i > 0 && colorIndex == lastIndex) // return false if two entries
- return false; // have the same index value
- }
- return true;
- }
-
-
- // —————————————————————————————————————————————————————————————————————————————
- //
- // CheckDisplay
- //
- // —————————————————————————————————————————————————————————————————————————————
- // This routine checks to see if the device in question is color, if
- // System 7 is running, and if there are ‘enough’ colors to draw the
- // title bar in color under System 7. This might not be the case if
- // the application is using a custom window palette.
- //
- // It does so in the same way that Apple’s system WDEF does. I essentially
- // took the assembly code that Apple released and made this use the same
- // algorithm.
- // —————————————————————————————————————————————————————————————————————————————
- Boolean
- CheckDisplay(short theDepth, short deviceFlags, GDHandle targetDevice,
- WindowPeek window)
- {
- Boolean inColor;
- Boolean use7Color = false; // Assume Black and White.
-
- if (theDepth >= 4 && (**targetDevice).gdType != fixedType && HasSystem7()) {
- // A passive matrix screen on a PowerBook is a fixed device type.
- // This seems to be how the Apple WDEF determines when to use black
- // and white on those displays.
-
- RGBColor testColor;
- GetWctbColor(window, wTingeLight, &testColor);
-
- // Check for B&W control panel setting.
- if (testColor.red != 0 || testColor.green != 0 || testColor.blue != 0)
- use7Color = true; // System 7.0 Color.
- }
- // Note: Since I didn’t find another way to see if the user had changed
- // the settings in the Color control panel to the Black-and-white setting,
- // I actually check to see if the rgb components of the light tinge color
- // are non-zero (which seemed to be the case with that setting).
-
- // Check to see if there are ‘enough’ colors to draw in color.
- inColor = HasCQDraw() && (deviceFlags & (0x0001 << gdDevType));
-
- if (use7Color && inColor && theDepth <= 8) {
- GDHandle saveDevice = GetGDevice();
- short ramp[5];
- // Make this array big enough for the largest ramp.
-
- use7Color = false;
- SetGDevice(targetDevice);
-
- ramp[0] = 0x00;
- ramp[1] = 0x07;
- ramp[2] = 0x08;
- ramp[3] = 0x0A;
- ramp[4] = 0x0D;
- if (CheckAvailable(window, wHiliteColorLight, wHiliteColorDark, 5, ramp)) {
- ramp[0] = 0x00;
- ramp[1] = 0x01;
- ramp[2] = 0x04;
- if (CheckAvailable(window, wTitleBarLight, wTitleBarDark, 3, ramp)) {
- ramp[0] = 0x00;
- ramp[1] = 0x04;
- ramp[2] = 0x0F;
- if (CheckAvailable(window, wTingeLight, wTingeDark, 3, ramp))
- use7Color = true;
- }
- }
- SetGDevice(saveDevice);
- }
-
- return use7Color;
- }
-
-
- // *****************************************************************************
- //
- // General Helper Functions
- //
- // *****************************************************************************
-
- // —————————————————————————————————————————————————————————————————————————————
- //
- // ColorsNormal
- //
- // —————————————————————————————————————————————————————————————————————————————
- void
- ColorsNormal()
- {
- ForeColor(blackColor);
- BackColor(whiteColor);
- }
-
-
- // —————————————————————————————————————————————————————————————————————————————
- //
- // MoveRectTo
- //
- // —————————————————————————————————————————————————————————————————————————————
- void
- MoveRectTo(Rect *theRect, short left, short top)
- {
- theRect->right += left - theRect->left;
- theRect->bottom += top - theRect->top;
- theRect->left = left;
- theRect->top = top;
- }
-
-
- // —————————————————————————————————————————————————————————————————————————————
- //
- // FrameBox
- //
- // —————————————————————————————————————————————————————————————————————————————
- void
- FrameBox(const Rect *theRect)
- {
- Rect tempRect = *theRect;
-
- FrameRect(theRect);
- InsetRect(&tempRect, 1, 1);
- EraseRect(&tempRect);
- }
-
-
- // —————————————————————————————————————————————————————————————————————————————
- //
- // FrameTopLeftShading
- //
- // —————————————————————————————————————————————————————————————————————————————
- void
- FrameTopLeftShading(Rect theRect)
- {
- theRect.right--; // Compensate for the way the rectangle hangs.
- theRect.bottom--;
-
- MoveTo(theRect.left, theRect.bottom); // •••••
- LineTo(theRect.left, theRect.top ); // •
- LineTo(theRect.right, theRect.top ); // •
- }
-
-
- // —————————————————————————————————————————————————————————————————————————————
- //
- // FrameBottomRightShading
- //
- // —————————————————————————————————————————————————————————————————————————————
- void
- FrameBottomRightShading(Rect theRect)
- {
- theRect.right--; // Compensate for the way the rectangle hangs.
- theRect.bottom--;
-
- MoveTo(theRect.left, theRect.bottom); // •
- LineTo(theRect.right, theRect.bottom); // •
- LineTo(theRect.right, theRect.top ); // •••••
- }
-
-
- // —————————————————————————————————————————————————————————————————————————————
- //
- // GetGlobalMappingPoint
- //
- // —————————————————————————————————————————————————————————————————————————————
- // This routine returns a point that gives the horizontal and vertical
- // offsets needed to map something into global coordinates.
- // —————————————————————————————————————————————————————————————————————————————
- void
- GetGlobalMappingPoint(WindowPeek window, Point *thePoint)
- {
- GrafPtr savePort;
-
- GetPort(&savePort);
- SetPort((GrafPtr) window);
-
- SetPt(thePoint, 0, 0);
- LocalToGlobal(thePoint);
-
- SetPort(savePort);
- }
-
-
- // —————————————————————————————————————————————————————————————————————————————
- //
- // GetGlobalContentRect
- //
- // —————————————————————————————————————————————————————————————————————————————
- void
- GetGlobalContentRect(WindowPeek window, Rect *contentRect)
- {
- Point mappingPoint;
-
- *contentRect = window->port.portRect;
- GetGlobalMappingPoint(window, &mappingPoint);
- OffsetRect(contentRect, mappingPoint.h, mappingPoint.v);
- }
-
-
- // —————————————————————————————————————————————————————————————————————————————
-